/**
 * 函数调用链提取器
 * 
 * 用于分析函数内部调用了哪些同文件内的其他函数，并提取这些函数的完整代码
 */

import * as vscode from 'vscode';
import { Logger } from '../../../src/logger/Logger';

export class FunctionCallChainExtractor {
    /**
     * 提取函数调用链（同文件内的函数调用）
     * 
     * @param functionCode 当前函数的代码
     * @param document 完整的文档
     * @returns 被调用函数的代码（包含函数名和完整实现）
     */
    public static async extractCalledFunctions(
        functionCode: string,
        document: vscode.TextDocument
    ): Promise<{ functionName: string; code: string }[]> {
        const calledFunctions: { functionName: string; code: string }[] = [];
        
        // 1. 提取函数内调用的函数名
        const calledNames = this.extractFunctionCalls(functionCode);
        
        if (calledNames.length === 0) {
            Logger.info(`[FunctionCallChainExtractor] 未检测到函数调用`);
            return calledFunctions;
        }
        
        Logger.info(`[FunctionCallChainExtractor] 检测到 ${calledNames.length} 个函数调用: ${calledNames.join(', ')}`);
        
        // 2. 在文档中查找这些函数的定义
        const fullText = document.getText();
        
        for (const name of calledNames) {
            const funcDef = this.findFunctionDefinition(name, fullText);
            if (funcDef) {
                calledFunctions.push({
                    functionName: name,
                    code: funcDef
                });
                Logger.info(`[FunctionCallChainExtractor]    ✓ 找到函数: ${name}`);
            } else {
                Logger.warn(`[FunctionCallChainExtractor]    ✗ 未找到函数: ${name} (可能在头文件或其他文件中)`);
            }
        }
        
        return calledFunctions;
    }
    
    /**
     * 从函数代码中提取函数调用
     */
    private static extractFunctionCalls(code: string): string[] {
        const calls = new Set<string>();
        
        // 匹配函数调用模式：functionName(...)
        // 排除：关键字（if, for, while, switch, return, sizeof, etc.）
        const keywords = new Set([
            'if', 'for', 'while', 'switch', 'return', 'sizeof', 'typeof',
            'static_cast', 'dynamic_cast', 'reinterpret_cast', 'const_cast',
            'alignof', 'decltype', 'noexcept', 'delete', 'new'
        ]);
        
        // 正则：匹配 xxx(...) 的模式，但排除 . 和 -> 前面的（成员调用）
        const funcCallRegex = /(?<![.\->])\b([a-zA-Z_][a-zA-Z0-9_]*)\s*\(/g;
        
        let match;
        while ((match = funcCallRegex.exec(code)) !== null) {
            const name = match[1];
            
            // 排除关键字
            if (!keywords.has(name)) {
                // 排除构造函数（通常是类型名，首字母大写）
                // 但保留如 CreateXxx, InitXxx 这种函数
                if (!/^[A-Z][a-z]/.test(name) || /^(Create|Init|Open|Close|Start|Stop|Get|Set|Make|Build)/.test(name)) {
                    calls.add(name);
                }
            }
        }
        
        return Array.from(calls);
    }
    
    /**
     * 在完整文本中查找函数定义
     */
    private static findFunctionDefinition(functionName: string, fullText: string): string | null {
        // 策略1: 匹配完整的函数定义（包含函数体）
        // 格式: returnType functionName(...) { ... }
        // 或: returnType ClassName::functionName(...) { ... }
        
        const patterns = [
            // 1. 普通函数定义
            new RegExp(
                `(\\w+(?:\\s*\\*|\\s*&)?\\s+${functionName}\\s*\\([^)]*\\)\\s*(?:const)?\\s*\\{[^{}]*(?:\\{[^{}]*\\}[^{}]*)*\\})`,
                'g'
            ),
            // 2. 类成员函数定义（带类名）
            new RegExp(
                `(\\w+(?:\\s*\\*|\\s*&)?\\s+\\w+::${functionName}\\s*\\([^)]*\\)\\s*(?:const)?\\s*\\{[^{}]*(?:\\{[^{}]*\\}[^{}]*)*\\})`,
                'g'
            )
        ];
        
        for (const pattern of patterns) {
            const match = pattern.exec(fullText);
            if (match) {
                return match[1].trim();
            }
        }
        
        // 策略2: 使用简化的嵌套括号匹配
        // 查找 "... functionName(...) {" 然后提取到匹配的 }
        const startRegex = new RegExp(
            `(\\w+(?:\\s*\\*|\\s*&)?\\s+(?:\\w+::)?${functionName}\\s*\\([^)]*\\)\\s*(?:const)?\\s*\\{)`,
            'g'
        );
        
        const startMatch = startRegex.exec(fullText);
        if (startMatch) {
            const startIndex = startMatch.index;
            const openBraceIndex = fullText.indexOf('{', startIndex);
            
            if (openBraceIndex >= 0) {
                // 查找匹配的闭合括号
                const endIndex = this.findMatchingBrace(fullText, openBraceIndex);
                if (endIndex >= 0) {
                    return fullText.substring(startIndex, endIndex + 1).trim();
                }
            }
        }
        
        return null;
    }
    
    /**
     * 查找匹配的闭合括号
     */
    private static findMatchingBrace(text: string, openIndex: number): number {
        let depth = 1;
        let inString = false;
        let inChar = false;
        let inComment = false;
        let inLineComment = false;
        
        for (let i = openIndex + 1; i < text.length; i++) {
            const char = text[i];
            const nextChar = i + 1 < text.length ? text[i + 1] : '';
            const prevChar = i > 0 ? text[i - 1] : '';
            
            // 处理行注释
            if (!inString && !inChar && !inComment && char === '/' && nextChar === '/') {
                inLineComment = true;
                i++; // 跳过 /
                continue;
            }
            
            if (inLineComment) {
                if (char === '\n') {
                    inLineComment = false;
                }
                continue;
            }
            
            // 处理块注释
            if (!inString && !inChar && char === '/' && nextChar === '*') {
                inComment = true;
                i++; // 跳过 *
                continue;
            }
            
            if (inComment) {
                if (char === '*' && nextChar === '/') {
                    inComment = false;
                    i++; // 跳过 /
                }
                continue;
            }
            
            // 处理字符串
            if (char === '"' && prevChar !== '\\' && !inChar) {
                inString = !inString;
                continue;
            }
            
            // 处理字符常量
            if (char === '\'' && prevChar !== '\\' && !inString) {
                inChar = !inChar;
                continue;
            }
            
            // 在字符串或字符常量中，忽略括号
            if (inString || inChar) {
                continue;
            }
            
            // 计算括号深度
            if (char === '{') {
                depth++;
            } else if (char === '}') {
                depth--;
                if (depth === 0) {
                    return i;
                }
            }
        }
        
        return -1; // 未找到匹配的括号
    }
    
    /**
     * 格式化提取的函数供 LLM 使用
     */
    public static formatForLLM(
        mainFunction: string,
        calledFunctions: { functionName: string; code: string }[]
    ): string {
        if (calledFunctions.length === 0) {
            return mainFunction;
        }
        
        let formatted = `// ===== 主函数 =====\n${mainFunction}\n\n`;
        formatted += `// ===== 被调用的函数（${calledFunctions.length}个）=====\n`;
        formatted += `// 这些函数在主函数中被调用，需要一并考虑测试覆盖\n\n`;
        
        calledFunctions.forEach(({ functionName, code }, index) => {
            formatted += `// --- 被调用函数 ${index + 1}: ${functionName} ---\n`;
            formatted += `${code}\n\n`;
        });
        
        return formatted;
    }
}

